#include "socket_util.h"

#include <sstream>

namespace qio {

int SetTimeout(Fd fd, std::size_t timeout_ms) QIO_NOEXCEPT {
#ifdef __WIN__
  DWORD tv = timeout_ms;
#else
  struct timeval tv {};
  tv.tv_sec = static_cast<std::int32_t>(timeout_ms / 1000);
  tv.tv_usec = static_cast<std::int32_t>((timeout_ms % 1000) * 1000);
#endif
  return socket_setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO,
                           reinterpret_cast<void *>(&tv), sizeof(tv));
}

IPAddress ParseSockAddrName4(const struct sockaddr_in *addr) QIO_NOEXCEPT {
  IPAddress out;
  static constexpr std::size_t add_str_len = 64;
  char addr_str[add_str_len];
  int err = uv_ip4_name(addr, addr_str, add_str_len);
  // TODO (suzhen) : log error
  if (err != 0) {
    return out;
  }
  out.addr = std::string(addr_str);
  out.port = addr->sin_port;
  return out;
}

int IPNameToSockAddr4(const std::string &name, std::uint16_t port,
                      struct sockaddr_in *out_addr) QIO_NOEXCEPT {
  return uv_ip4_addr(name.c_str(), port, out_addr);
}

IPAddress::IPAddress() QIO_NOEXCEPT : IPAddress("", 0) {}

IPAddress::IPAddress(const std::string &addr, std::uint16_t port) QIO_NOEXCEPT
    : addr(addr),
      port(port) {}

std::string IPAddress::ToString() const QIO_NOEXCEPT {
  std::stringstream ss;
  ss << addr << ":" << port;
  return ss.str();
}

}  // namespace qio